package com.edu.chat.web.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.edu.buservice.util.model.TenantUtil;
import com.edu.chat.facade.model.dto.SceneInfoDTO;
import com.edu.chat.facade.model.dto.SessionInfoDetailDTO;
import com.edu.chat.web.common.enums.ResultCodeEnum;
import com.edu.chat.web.common.enums.SessionStatusEnum;
import com.edu.chat.web.common.model.BizException;
import com.edu.chat.web.common.model.R;
import com.edu.chat.web.controller.vo.PageQuery;
import com.edu.chat.web.controller.vo.SessionVO;
import com.edu.chat.web.covert.SessionCovert;
import com.edu.chat.web.dto.PageResult;
import com.edu.chat.web.mapper.CsSessionMapper;
import com.edu.chat.web.model.CsSession;
import com.edu.chat.web.service.CsSceneService;
import com.edu.chat.web.service.CsSessionService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author 86177
 * @description 针对表【cs_session(会话信息表)】的数据库操作Service实现
 * @createDate 2025-03-23 18:22:09
 */
@Service
@Slf4j
public class CsSessionServiceImpl extends ServiceImpl<CsSessionMapper, CsSession>
		implements CsSessionService{

	@Autowired
	@Lazy
	private CsSceneService csSceneService;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public R<SessionInfoDetailDTO> createSession(SessionVO sessionVO) {

		log.info("SessionController createSession 创建会话，参数：{}", sessionVO);

		//校验数据
		if(sessionVO == null){
			return R.fail(ResultCodeEnum.PARAM_INVALID, "sessionVO is null");
		}

		//获取用户真实租户ID
		String tenantId = TenantUtil.getTenantId();

		//设置租户ID
		TenantUtil.setCurrentTenantId(sessionVO.getTenantId());

		//获取聊天窗信息
		SceneInfoDTO sceneInfoDTO = csSceneService.querySceneInfoById(Long.parseLong(sessionVO.getSceneId()));

		if(sceneInfoDTO == null){
			return R.fail(ResultCodeEnum.PARAM_INVALID, "sceneInfoDTO is null");
		}

		//判断聊天窗是否开启
		if(!sceneInfoDTO.getStatus().equals(1)){
			return R.fail(ResultCodeEnum.REQUEST_NOT_SUPPORTED, "聊天窗已关闭暂时不支持提供功能");
		}

		CsSession csSession = new CsSession();
		csSession.setRobotId(Long.parseLong(sceneInfoDTO.getRobotId()));
		csSession.setUserId(StpUtil.getLoginIdAsLong());
		csSession.setSceneId(Long.valueOf(sessionVO.getSceneId()));
		csSession.setId(IdUtil.getSnowflakeNextId());
		csSession.setDeleted(0);
		csSession.setName(Optional.ofNullable(sessionVO.getSessionName()).orElse("你猜"));
		csSession.setStatus(SessionStatusEnum.ACTIVE.getCode());
		save(csSession);

		TenantUtil.setCurrentTenantId(tenantId);

		//构建返回数据
		SessionInfoDetailDTO sessionInfoDetailDTO = new SessionInfoDetailDTO();
		sessionInfoDetailDTO.setTitle(csSession.getName());
		sessionInfoDetailDTO.setTenantId(tenantId);
		sessionInfoDetailDTO.setSessionId(String.valueOf(csSession.getId()));
		sessionInfoDetailDTO.setSceneInfo(sceneInfoDTO);
		sessionInfoDetailDTO.setStatus(csSession.getStatus());
		sessionInfoDetailDTO.setUserId(String.valueOf(csSession.getUserId()));

		return R.success(sessionInfoDetailDTO);
	}

	@Override
	public R<SessionInfoDetailDTO> getSessionInfo(String sessionId) {

		log.info("getSessionInfo sessionId:{}",sessionId);

		if(sessionId == null){
			throw new BizException(ResultCodeEnum.PARAM_INVALID,"sessionId不能为空");
		}


		LambdaQueryWrapper<CsSession> queryWrapper=new LambdaQueryWrapper<>();

		queryWrapper.eq(CsSession::getId,sessionId);
		queryWrapper.eq(CsSession::getDeleted,0);
		CsSession csSession = getOne(queryWrapper);

		if(Objects.isNull(csSession)){
			throw new BizException(ResultCodeEnum.DATA_NOT_FOUND,"会话不存在");
		}

		SceneInfoDTO sceneInfoDTO = csSceneService.querySceneInfoById(csSession.getSceneId());


		return R.success(SessionCovert.convert(csSession, sceneInfoDTO));

	}

	@Override
	public PageResult<SessionInfoDetailDTO> listSession(PageQuery<SessionVO> pageQuery) {
		// 校验输入参数
		if (pageQuery == null) {
			throw new BizException(ResultCodeEnum.PARAM_INVALID, "pageQuery不能为空");
		}

		SessionVO query = pageQuery.getQuery();
		if (pageQuery.getPageNum() == null || pageQuery.getPageSize() == null) {
			throw new BizException(ResultCodeEnum.PARAM_INVALID, "分页参数不能为空");
		}

		LambdaQueryWrapper<CsSession> queryWrapper = new LambdaQueryWrapper<>();

		String tenantId = TenantUtil.getTenantId();

		// 获取用户ID，默认使用登录用户ID
		if(query != null){
			String userId = Optional.ofNullable(query.getUserId())
					.orElseGet(StpUtil::getLoginIdAsString);

			TenantUtil.setCurrentTenantId(query.getTenantId());

			// 构建查询条件
			queryWrapper = buildQueryWrapper(query, userId);
		}

		// 分页查询
		IPage<CsSession> pageParam = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize());
		IPage<CsSession> pageResult = page(pageParam, queryWrapper);

		if (Objects.isNull(pageResult)) {
			throw new BizException(ResultCodeEnum.DATABASE_ERROR, "数据库查询失败");
		}

		// 构建结果集
		PageResult<SessionInfoDetailDTO> res = new PageResult<>();
		res.setTotal(pageResult.getTotal());
		res.setCurrentPage(pageResult.getCurrent());
		res.setTotalPages(pageResult.getPages());

		TenantUtil.setCurrentTenantId(tenantId);

		// 批量获取场景信息并转换为 DTO
		List<SessionInfoDetailDTO> list = convertSessionsToDTO(pageResult.getRecords());
		res.setRecords(list);

		return res;
	}

	@Override
	public R<Boolean> updateSessionName(String sessionId, String sessionName) {

		if(sessionId == null){
			throw new BizException(ResultCodeEnum.PARAM_INVALID,"sessionId不能为空");
		}

		if(sessionName == null){
			throw new BizException(ResultCodeEnum.PARAM_INVALID,"sessionName不能为空");
		}


		LambdaUpdateWrapper<CsSession> updateWrapper = new LambdaUpdateWrapper<>();
		updateWrapper.eq(CsSession::getId, sessionId)
				.set(CsSession::getName, sessionName);


		if(update(updateWrapper)){
			return R.success(true);
		}

		return R.fail("更新异常");
	}

	@Override
	public List<CsSession> querySessionByTenantIdAndTime(String tenantId, String startTime, String endTime) {
		// 租户ID处理
		String currentTenantId = StringUtils.isNotBlank(tenantId) ? tenantId : TenantUtil.getTenantId();
		if (StringUtils.isBlank(currentTenantId)) {
			throw new IllegalArgumentException("Invalid tenant ID");
		}
		TenantUtil.setCurrentTenantId(currentTenantId);

		// 时间处理
		Date now = new Date();
		String effectiveStart = StringUtils.defaultIfBlank(startTime, DateUtil.format(DateUtil.offsetDay(now, -7), "yyyy-MM-dd"));
		String effectiveEnd = StringUtils.defaultIfBlank(endTime, DateUtil.format(DateUtil.endOfDay(now), "yyyy-MM-dd"));

		DateTime begin = DateUtil.parse(effectiveStart);
		DateTime end = DateUtil.parse(effectiveEnd);

		if (begin.after(end)) {
			throw new IllegalArgumentException("Start time cannot be after end time");
		}

		LambdaQueryWrapper<CsSession> csSessionLambdaQueryWrapper = new LambdaQueryWrapper<CsSession>()
				.eq(CsSession::getTenantId, currentTenantId)
				.between(CsSession::getCreatedAt, begin, end)
				.eq(CsSession::getDeleted, 0)
				.orderByDesc(CsSession::getCreatedAt);

		return list(csSessionLambdaQueryWrapper);



	}



	// 构建查询条件
	private LambdaQueryWrapper<CsSession> buildQueryWrapper(SessionVO query, String userId) {
		LambdaQueryWrapper<CsSession> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(CsSession::getUserId, userId)
				.eq(CsSession::getDeleted, 0)
				.orderByDesc(CsSession::getCreatedAt);

		Optional.ofNullable(query.getSessionName()).ifPresent(name -> queryWrapper.like(CsSession::getName, name));
		Optional.ofNullable(query.getSceneId()).ifPresent(sceneId -> queryWrapper.eq(CsSession::getSceneId, sceneId));
		Optional.ofNullable(query.getStatus()).ifPresent(status -> queryWrapper.eq(CsSession::getStatus, status));
		Optional.ofNullable(query.getTenantId()).ifPresent(tenantId -> queryWrapper.eq(CsSession::getTenantId, tenantId));

		return queryWrapper;
	}

	// 批量转换会话数据为 DTO
	private List<SessionInfoDetailDTO> convertSessionsToDTO(List<CsSession> sessions) {
		if (sessions == null || sessions.isEmpty()) {
			return Collections.emptyList();
		}

		// 提取所有场景ID
		Set<Long> sceneIds = sessions.stream()
				.filter(Objects::nonNull)
				.map(CsSession::getSceneId)
				.filter(Objects::nonNull)
				.collect(Collectors.toSet());

		// 批量查询场景信息
		Map<String, SceneInfoDTO> sceneInfoMap = sceneIds.stream()
				.map(id -> csSceneService.querySceneInfoById(id))
				.filter(Objects::nonNull)
				.collect(Collectors.toMap(SceneInfoDTO::getSceneId, Function.identity()));

		// 转换为 DTO
		return sessions.stream()
				.map(session -> {
					SceneInfoDTO sceneInfoDTO = sceneInfoMap.get(String.valueOf(session.getSceneId()));
					return SessionCovert.convert(session, sceneInfoDTO);
				})
				.toList();
	}

}




